﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using Avalon.Windows.Controls;
using Csla.Core;

using OpenExpressApp.MetaModel;
using OpenExpressApp.Module.WPF.Editors;
using OpenExpressApp.Module.WPF.Editors.TreeColumn;
using OpenExpressApp.Template;
using OpenExpressApp.WPF.Controls;
using OpenExpressApp.WPF.Editors;
using Ricciolo.Controls;
using OpenExpressApp.Command;

namespace OpenExpressApp.Module.WPF
{
    public static class ExtensionMethods
    {
        /// <summary>
        /// 生成该属性的Grid列对象
        /// </summary>
        /// <param name="property"></param>
        /// <param name="view"></param>
        /// <returns></returns>
        public static DataGridColumn CreateDefaultGridColumn(this BusinessObjectPropertyInfo property, IListObjectView view)
        {
            DataGridColumn dataGridColumn = null;
            // DataGridComboBoxColumn comboBoxColumn = null;
            Type propertyType = property.PropertyType;

            #region 生成一个新的DataGridColumn

            //if (typeof(bool).IsAssignableFrom(propertyType))
            //{
            //    dataGridColumn = new DataGridCheckBoxColumn();
            //}
            if (typeof(Uri).IsAssignableFrom(propertyType))
            {
                dataGridColumn = new DataGridHyperlinkColumn();
            }
            else
            {
                //dataGridColumn =  new DataGridTextColumn();
                dataGridColumn = GridColumnsFactory.GetDefaultColumn(property.EditorName, property, view);

            }

            #endregion

            //如果是下拉，则获取这个列的引用
            //if (property.EditorName == EditorNames.LookupDropDown)
            //{
            //    comboBoxColumn = dataGridColumn as DataGridComboBoxColumn;
            //}

            // determine if the datagrid can sort on the column or not
            if (typeof(IComparable).IsAssignableFrom(propertyType) == false)
            {
                dataGridColumn.CanUserSort = false;
            }

            dataGridColumn.Header = property.Label;

            DataGridBoundColumn boundColumn = dataGridColumn as DataGridBoundColumn;

            //是DataGridBoundColumn或DataGridComboBoxColumn
            //Set the data field binding for such created columns and 
            //choose the BindingMode based on editability of the property.
            if (boundColumn != null)
            {
                Binding binding = new Binding(property.Name);
                //如果是只读属性，则设置binding mode
                if (property.RuntimeProperty.CanWrite == false)
                {
                    binding.Mode = BindingMode.OneWay;
                }
                boundColumn.Binding = binding;
            }
            return dataGridColumn;
        }
        /// <summary>
        /// 生成TreeListView列对象
        /// </summary>
        /// <param name="property"></param>
        /// <param name="view"></param>
        /// <returns></returns>
        public static GridViewColumn CreateDefaultTreeColumn(this BusinessObjectPropertyInfo property, IListObjectView view)
        {
            GridViewColumn c = new GridViewColumn();
            c.SetValue(Control.NameProperty, property.Name);  //设置一个名称，以便后面切换编辑样式时设置绑定路径
            c.SetValue(WPFMeta.BOPropInfoProperty, property);  //存储info,以便后面更新编辑方式使用
            c.Header = property.Label;

            //不能设置DisplayMemberBinding，否则WPF底层实现时不会根据cellTemplete来生成显示控件，而默认都使用TextBlock来显示了
            //c.DisplayMemberBinding = new Binding(info.Name);  
            if ((property.IsTitle) || (null != property.LookupAttribute))
            {
                c.Width = 200;
            }
            else
            {
                c.Width = 100;
            }

            DataTemplate dt = new DataTemplate();
            TreeColumn treeColumn = TreeColumnsFactory.GetDefaultTreeColumn(property.EditorName, property, view);
            treeColumn.GridViewColumn = c;
            dt.VisualTree = treeColumn.GenerateFrameworkElementFactory();
            c.SetValue(WPFMeta.TreeColumnProperty, treeColumn);  //存储info,以便后面更新编辑方式使用
            c.CellTemplate = dt;

            return c;
        }

        /// <summary>
        /// 以对话框的形式显示错误信息
        /// </summary>
        /// <param name="error"></param>
        public static void ShowError(this Exception error)
        {
            Exception ex = LastInnerException(error);
            TaskDialog taskDialog = new TaskDialog
            {
                Width = 600,
                Title = "错误",
                Header = "错误",
                Content = ex.Message,
                ExpansionPosition = TaskDialogExpansionPosition.Footer,
                ExpansionButtonContent = "详细信息",
                ExpansionContent = new TextBox()
                {
                    AcceptsReturn = true,
                    Text = error.ToString(),
                    Height = 300
                },
            };

            taskDialog.Show();
        }

        private static Exception LastInnerException(Exception ex)
        {
            Exception result = ex;
            while (null != result)
            {
                if (null == result.InnerException)
                {
                    return result;
                }
                result = result.InnerException;
            }
            return ex;
        }

        /// <summary>
        /// 找到最上层的IFrameTemplate
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        public static IFrameTemplate GetFrameTemplate(this FrameworkElement element)
        {
            DependencyObject currentElement = element;

            while (currentElement != null)
            {
                if (typeof(IFrameTemplate).IsAssignableFrom(currentElement.GetType()))
                {
                    return currentElement as IFrameTemplate;
                }

                currentElement = LogicalTreeHelper.GetParent(currentElement) ??
                    VisualTreeHelper.GetParent(currentElement);
            }

            return null;
        }
        public static IFrameTemplate GetFrameTemplate(this ObjectView view)
        {
            return (view.Control as FrameworkElement).GetFrameTemplate();
        }

        #region Used for testing EditLevel

        //public static bool HasInconsistentEditLevel(this BusinessBase model)
        //{
        //    return HasInconsistentEditLevel(model, model.GetEditLevel());
        //}
        //public static bool HasInconsistentEditLevel(this BusinessBase model, int targetEditLevel)
        //{
        //    if (model.GetEditLevel() != targetEditLevel)
        //    {
        //        return true;
        //    }
        //    var boInfo = ApplicationModel.GetBusinessObjectInfo(model.GetType());
        //    foreach (var propInfo in boInfo.BOsPropertyInfos)
        //    {
        //        var children = model.GetPropertyValue(propInfo.Name) as IEnumerable;
        //        foreach (BusinessBase child in children)
        //        {
        //            if (HasInconsistentEditLevel(child, targetEditLevel))
        //            {
        //                return true;
        //            }
        //        }
        //    }

        //    return false;
        //}
        //public static int GetEditLevel(this BusinessBase model)
        //{
        //    return (model as IUndoableObject).EditLevel;
        //}

        #endregion
    }

    public static class DependencyObjectExtensionMethods
    {
        /// <summary>
        /// Returns the first visual child from parent based on T
        /// </summary>        
        public static T GetVisualChild<T>(this Visual parent) where T : Visual
        {
            T child = default(T);

            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                child = v as T;
                if (child == null)
                {
                    child = GetVisualChild<T>(v);
                }
                if (child != null)
                {
                    break;
                }
            }

            return child;
        }

        public static T GetVisualChild<T>(this Visual parent, int index) where T : Visual
        {
            T child = default(T);

            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                child = v as T;
                if (child == null)
                {
                    continue;
                }
                if (child != null && i == index)
                {
                    break;
                }
            }

            return child;
        }

        public static T GetLogicalParent<T>(this DependencyObject child) where T : Visual
        {
            DependencyObject v = LogicalTreeHelper.GetParent(child);
            if (null == v)
            {
                return null;
            }
            else if ((v != null) && (v is T))
            {
                return (T)v;
            }
            else
            {
                return v.GetLogicalParent<T>();
            }
        }
    }
}